#include <stdio.h>
#include <stdlib.h>
#include "slave.h"
#include <assert.h>
#include "args.h"
#include "aceMesh_utils.h"
#include "aceMesh_task.h"
#include "aceMesh_runtime.h"
#include "helper_slave.h"
#include "ci_task.h"


// __thread_local volatile int buffer_owner[HELPER_BUFFER_COUNT] = {0}; //buffer所有权初始化在主核
 volatile unsigned long __uncached buffer_owner[HELPER_BUFFER_COUNT] = {0};
__thread_local volatile int buffer_own[HELPER_BUFFER_COUNT];

volatile

 struct slave_work_buffer sl_buffers[64][HELPER_BUFFER_COUNT];

__thread_local volatile int own_buf_idx=0;
__thread_local volatile int build_end;
volatile new_slave_table tables[64];
volatile unsigned long __uncached construct_end=0;
__thread_local volatile int cons_over=0;

// volatile int slave_finished[64] = {0}; 
// __thread_local volatile  int slave_finished ; 
volatile unsigned long __uncached slave_exited = 0;
__thread_local volatile int exit_sig=0;

volatile int time_begin_flag=0;

#ifdef MASTER_UNION_TOP
__thread_local_fix void *local_top1[TOP_WINDOW];
__thread_local_fix volatile int topnum=0;
void *local_task_top[HELPER_NUM][TOP_WINDOW];
#endif
#ifdef SLAVE_UNION_TOP
extern __thread_local_fix struct top_level_buff tl_buffer[NT];
extern __thread_local_fix volatile int top_sig;
#endif
// __thread_local struct MemPool slave_pool_ldm;
__thread_local_fix int collision_item_count;


// __uncached volatile int slave_init_done=0;

#define remote_ldm(coreid,ldm_var) ((unsigned long)&ldm_var | ((unsigned long)coreid << 20 ) |(1ULL << 45))
#ifdef ACEMESH_GRAPH_BUILD_PROFILING
#ifdef FINE_PROF
extern double all_pure_addsucc_time[64];
__thread_local_fix double add_succ_start=0.0;
__thread_local_fix double add_succ_end=0.0;

extern double all_pure_register_time[64];
__thread_local_fix double reg_access_start=0.0;
__thread_local_fix double reg_access_end=0.0;

#endif
extern unsigned long buil_prof[N_BUILD_PROF];
// unsigned long add_succ_start;
#endif

#ifdef FLAT_CONSTRUCT_HELEPR
#ifdef SLAVE_UNION_TOP
// 计算四个local_task_top子数组的去重并集，并存储在result数组中  
// result数组应该预先分配足够的空间来存储可能的最大并集大小  
int findUnion(void* local_task_top[HELPER_NUM][TOP_WINDOW], void* result[]) {  
    int topSize = 0; // 初始化结果大小为0  
  
    // 四个指针，分别指向四个子数组的当前元素  
    int pointers[HELPER_NUM] = {0};  
    bool hasEnded[HELPER_NUM] = {false}; // 标记每个子数组是否已遍历完  
    while (true) {  
        // 找到当前最小的元素及其索引  
        void* minElement = NULL;  
        // void* minElement = taskBBS[0];  
        int minIndex = -1;  
        for (int i = 0; i < HELPER_NUM; ++i) {  
            if (!hasEnded[i] && (minElement == NULL || local_task_top[i][pointers[i]] < minElement)) {  
                minElement = local_task_top[i][pointers[i]];  
                minIndex = i;  
            }  
        }  
  
        // 如果没有找到最小元素，说明所有子数组都已遍历完  
        if (minElement == NULL) {  
            break;  
        }  
  
        // 将最小元素添加到结果中（如果它还没有被添加过）  
        bool isDuplicate = false;  
        for (int j = 0; j < topSize; ++j) {  
            if (result[j] == minElement) {  
                isDuplicate = true;  
                break;  
            }  
        }  
        if (!isDuplicate) {  
            result[topSize++] = minElement;  
            assert(topSize<=SEND_TASK_WINDOW);
        }  
  
        // 移动找到最小元素的子数组的指针  
        ++pointers[minIndex];  
        assert(minIndex<HELPER_NUM);
        assert(pointers[minIndex]<TOP_WINDOW);
        // 如果该子数组已遍历完，则标记为已结束  
        if (pointers[minIndex] >= TOP_WINDOW || local_task_top[minIndex][pointers[minIndex]] == NULL) {  
            hasEnded[minIndex] = true;  
        }  
    }  
    return topSize;
}  
#endif
inline void init_slave_table(int id) {  //分布式哈希表初始化
    int i;
    for (i = 0; i < SLAVE_TBL_SIZE; i++) {
        tables[id].items[i].data_addr = NULL;
        tables[id].items[i].data_access =NULL;
        tables[id].items[i].succ = NULL;
    }
    tables[id].col_idx = 0;
    for (i = 0; i < COLLISION_BUF_SIZE; i++) {
        tables[id].col_items[i].data_addr = NULL;
        tables[id].col_items[i].data_access =NULL;
        tables[id].col_items[i].succ = NULL;
    }
}
void init_slave_buffer_and_table(int id) {  //初始化两个buffer的所有权
    int i;
    for (i = 0; i < HELPER_BUFFER_COUNT; i++) {  //buffer数目（HELPER_BUFFER_COUNT）=2
        sl_buffers[id][i].idx = 0;  //idx:当前空位坐标
        buffer_owner[i] = BUF_OWNER_MASTER;  //每个buffer的控制权限初始化在主核
        buffer_own[i]= BUF_OWNER_MASTER;
    }

//#ifndef SLAVE_HELPER_WINDOW
    init_slave_table(id);
		// printf("哈希表%d初始化完毕\n",id);
//#endif
}
#endif
// #ifdef DISTRIBUTE_TOP

#ifdef DISTRIBUTE_TOP
#ifdef SLAVE_UNION_TOP
void init_tl_buffer()
{
    int i;
    for(i=0;i<NT;i++){
       tl_buffer[i].head=0;
       tl_buffer[i].tail=0;
    }
}
#endif
#endif
// void init_localtop_buffer(int id)
// {
//     int i;
//     for(i=0;i<NT;i++){
//        local_top[id].top_index=0;
//        local_top[id].top_task[TOP_WINDOW]=NULL;
//     }
// }

// #endif

void add_succ(struct DataAccess *succ_access, struct DataAccess *pre_access)

{
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//     add_succ_start=rtc();
// 		// unsigned long addsucc_start=rtc();
// #endif
     //printf("tbl任务类型%dtblDA地址%p任务地址%ptbl任务地址%p,\n",tbl->data_access->_type,tbl->data_access,data_access->_originator,tbl->data_access->_originator);
#ifdef CONCURRENT_CONSTRUCT_FATGRAPH 
    if(pre_access!=NULL&&pre_access->deleted==0){
        //  if(pre_access!=NULL&&pre_access->_originator->_endExecute==0){
            slave_my_mutex_lock(&(pre_access->countlock));
            //    if(pre_access!=NULL&&pre_access->_originator->_endExecute==0){
            if(pre_access!=NULL&&pre_access->deleted==0){

#else
    if(pre_access!=NULL){
#endif
        if(pre_access->_type==IN && succ_access->_type==IN && pre_access->_accessFlags==SATISFIED){   //识别第一层，前驱是已经就绪的R，新增加剧的R也是自然就绪的，仅连接不阻塞
            slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
            slave_set_unblock_Successor(pre_access,succ_access); //R1-R2,R1是top，R2为ready					
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
#ifdef MASTER_UNION_TOP
        assert(topnum<=TOP_WINDOW);
          local_top1[topnum++]=succ_access->_originator;
#endif
#ifdef SLAVE_UNION_TOP
       	struct top_level_buff *cur_top=remote_ldm(7,tl_buffer[_MYID]);
		int local_tail=(cur_top->tail+1)%HELPER_BUFF_SIZE; 
              //队列满就一直循环等待
        while(cur_top->head==local_tail){
        }  
        cur_top->top_task[cur_top->tail]=succ_access->_originator;
        cur_top->tail=local_tail;
        // printf("填充%d\n",local_tail);
#endif
        
#endif  
				//  asm volatile ("memb\n");
					 // printf("不阻塞的前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator);
         }else { // 以上三个条件，任一不满足，都说明存在实际的依赖（R-W，W-R，W-W，W-R-R），必须修改引用计数
#ifdef CONCURRENT_CONSTRUCT_FATGRAPH                
                    // if(pre_access->deleted==0){
                    //     // printf("*********上锁%p\n",succ_access);
                    //     slave_my_mutex_lock(&(pre_access->countlock));
                    //       if(pre_access->deleted==0){
                //   if(pre_access->_originator->_endExecute!=1){ //前驱任务未执行完才建边
                  
                    //if(pre_access->_originator->_endExecute==0){
#endif            
                   slave_setSuccessor(pre_access,succ_access);   
#ifdef CONCURRENT_CONSTRUCT_FATGRAPH
                    // }
                  
                // }
                //  slave_my_mutex_unlock(&(pre_access->countlock));
                // //   printf("*********解锁%p\n",succ_access);
                // // else{
                // //     slave_my_mutex_unlock(&(succ_access->countlock));
                //  }
#endif 
						// asm volatile ("memb\n");
           // printf("前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator); 
        }   
#ifdef CONCURRENT_CONSTRUCT_FATGRAPH         
            slave_my_mutex_unlock(&(pre_access->countlock));
    }
#endif


    }else{
        if(succ_access->_type==IN){ //该地址没有前驱，且类型为读，则设置addr.top=true
            slave_set_access_state(1, &(succ_access->top));
						// asm volatile ("memb\n");
       // printf("设置%p为top%d\n",data_access,data_access->top);
        }
        slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
	
#ifdef MASTER_UNION_TOP
        assert(topnum<=TOP_WINDOW);
          local_top1[topnum++]=succ_access->_originator;
#endif
#ifdef SLAVE_UNION_TOP
       	struct top_level_buff *cur_top=remote_ldm(7,tl_buffer[_MYID]);
		int local_tail=(cur_top->tail+1)%HELPER_BUFF_SIZE; 
              //队列满就一直循环等待
        while(cur_top->head==local_tail){
        }  
        cur_top->top_task[cur_top->tail]=succ_access->_originator;
        cur_top->tail=local_tail;
        // printf("填充%d\n",local_tail);
#endif
	
#endif 
}
    //printf("设置succ\n");
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//      buil_prof[SUB_ADD_SUCC]+=(rtc()-add_succ_start);
// 		 add_succ_end=rtc();
// 		all_pure_addsucc_time[_MYID]+=(double)(add_succ_end-add_succ_start)/SFREQ;
// #endif
}

inline struct new_slave_table_item * new_get_collision_buffer_item(int id)
{
    //printf("tables[_MYID]->col_idx %d\n",tables[_MYID]->col_idx );
    assert(tables[id].col_idx  < COLLISION_BUF_SIZE);
       if (tables[id].col_idx >= COLLISION_BUF_SIZE) {
        int i;
        int empty = 0;
        for (i = 0; i < SLAVE_TBL_SIZE; i++) {
            if (tables[id].items[i].data_addr == NULL) {
                empty++;
            }
        }
        printf("empty rate: %f\n", (float)empty / SLAVE_TBL_SIZE);
        fflush(stdout);
        // assert(0);
    }
   struct new_slave_table_item * item = &(tables[id].col_items[tables[id].col_idx]);
    tables[id].col_idx++;
    return item;
}


void worker_help_func()
{

// #ifdef DEBUG_PBH
#ifdef DEBUG_CONCURRENT  

	printf("%dhelper轮询开始\n",_MYID);
  fflush(stdout);
#endif
    int ltid=_MYID%8;
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
// 		unsigned long init_hash=rtc();
// #endif
       
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//     buil_prof[INIT_HASH]+=(rtc()-init_hash);
// #endif
		
		int main_finished = 0;
        build_end=1;
        // slave_finished=0;
		slave_work_buffer stack_buf;
		int i,j;
         construct_end=&cons_over; //没有必要放在while循环里，好像放外面也可以
         slave_exited=&exit_sig;  
         buffer_owner[own_buf_idx]=&buffer_own[own_buf_idx];
          
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    add_succ_start=rtc();
#endif
 while (1) { //helper一直轮询

        if (cons_over) {
            main_finished = 1; 
        // printf("******从核%d可以结束\n",_MYID);
        }
         //flush_slave_cache();

#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
       reg_access_start=rtc();
#endif 
        if (buffer_own[own_buf_idx]== BUF_OWNER_SLAVE) {  //buffer权限此时在从核
        //  printf("buffer%d权限此时在从核own_buf_idx%d\n",_MYID,own_buf_idx);
            int k = 0;
            slave_helper_item * item = NULL;
            int tbl_idx = 0;
             build_end=0;
            volatile unsigned long dma_reply = 0;
            athread_get(0, &(sl_buffers[_MYID][own_buf_idx]), &stack_buf, sizeof(slave_work_buffer), (void*)&dma_reply, 0, 0, 0);
            while (dma_reply != 1)
                ;
    // #ifdef SLAVE_HELPER_PROF
    //         update_task += stack_buf.idx;
    // #endif
            //  printf("MYID%dbuffer%d权限此时在从核idx%d\n",_MYID,own_buf_idx,stack_buf.idx);
            for (k = 0; k < stack_buf.idx; k++) {
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//        unsigned long reg_start=rtc();
// #endif             
                item = &(stack_buf.items[k]);
               assert(item!=NULL);
#ifdef MATSER_MULZTI_CORE_C 
                struct ci_task *cur_task=item->item_task;
                struct DataAccess *access=item->item_access;
                void *address=item->item_address;              
		        int type=item->item_type;
                // access->_originator=(struct task*)cur_task;
                // access->_successor=NULL;
                // access->_type=type;
                // access->_accessFlags=INITED;
                // access->top=0;
                slave_initialize(access,type,&(cur_task->aceMesh_task_base.task_base),INITED,0);
		        unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
               // printf("slave_initialize%d\n",k);
#else
                void *address=item->item_address;
                unsigned long hash_value=item->item_hash;
                struct DataAccess *access=item->item_access;
#endif
#ifdef TEMP_ENDTASK_SLAVE
               if(hash_value==999999){   //最后一个dfendTask
                    // for(int i=8;i<8+HELPER_NUM;i++){//等到helper构图完就可以设置endTask，此时的tables就是最后的tables了
                    struct DataAccess *preaccess=NULL;
                    for (int j = 0; j < SLAVE_TBL_SIZE; j++) {
                        preaccess=tables[_MYID].items[j].data_access;
                        if(preaccess!=NULL){
                        if(preaccess!=NULL&&preaccess->deleted==0){
                              slave_my_mutex_lock(&(preaccess->countlock));
                            if(preaccess!=NULL&&preaccess->deleted==0){
                                slave_setSuccessor(preaccess,access);
                            }
                            slave_my_mutex_unlock(&(preaccess->countlock));

                        }
                    
                    }
                    }
                    for (int k = 0; k < COLLISION_BUF_SIZE; k++) {
                        preaccess=tables[_MYID].col_items[k].data_access;
                        if(preaccess!=NULL){
                        if(preaccess!=NULL&&preaccess->deleted==0){
                              slave_my_mutex_lock(&(preaccess->countlock));
                            if(preaccess!=NULL&&preaccess->deleted==0){
                           slave_setSuccessor(preaccess,access);
                            }
                              slave_my_mutex_unlock(&(preaccess->countlock));

                        }
                    }
                }
                int num=slave_predec_count(access->_originator);
              printf("**********endTask%p前驱计数个数为%d\n",access->_originator,num);
            }
#endif
                // tbl_idx = ((item->hash_value) >> 44) & 0xffff;  //取高20位中的低16位，65536			

                //assert(access==NULL);
                // int id=item->item_id;
                struct DataAccess *predecessor=NULL;
                    // tbl_idx = ((hash_value) >> 44) & 0xffff; ////取高20位(高位的变化更大)中的低16位，65536
                 tbl_idx =  ((hash_value) >> 44) & 0x3fff; //size 16384
                //  tbl_idx =  ((hash_value) >> 44) & 0x7fff; //size 32768
                //   tbl_idx =  ((hash_value) >> 44) & 0x1fff; //size 8192
                 assert(tbl_idx<SLAVE_TBL_SIZE);
                // printf("tbl_idx%d,\n",tbl_idx);
                //printf("@@slave_initialize%d\n",k);
                if (tables[_MYID].items[tbl_idx].data_addr == address) {  //哈希表存在地址
                            predecessor=tables[_MYID].items[tbl_idx].data_access;
                                slave_add_succ(access, predecessor);
                                    tables[_MYID].items[tbl_idx].data_access=access; //更新哈希表
                                    asm volatile ("memb\n");
                                 //   printf("@@@@slave_initialize%d\n",k);
                }
                else if (tables[_MYID].items[tbl_idx].data_addr == NULL) { //哈希表不存在此地址
                        predecessor=tables[_MYID].items[tbl_idx].data_access; //NULL
                        tables[_MYID].items[tbl_idx].data_addr = address;
                        slave_add_succ(access, predecessor);
                        tables[_MYID].items[tbl_idx].data_access=access; //更新哈希表
                        asm volatile ("memb\n");
                          // printf("@@@@@slave_initialize%d\n",k);
                }
                else {
                        //printf("哈希冲突%p\n",address);
                        struct new_slave_table_item * col_item = NULL;
                        struct new_slave_table_item * temp = &(tables[_MYID].items[tbl_idx]);
                        while (temp->succ != NULL) { 
                                //struct new_slave_table_item *temp_item=NULL;
                                //temp_item=temp->succ;
                                if (temp->succ->data_addr == address) {  
                                        predecessor=temp->succ->data_access;
                                        slave_add_succ(access, predecessor);
                                        temp->succ->data_access=access; //更新哈希表
                                        asm volatile ("memb\n");
                                        goto update_complete;
                                }
                                temp = temp->succ;   
                        
                        }     
                        collision_item_count++; 
                        col_item = new_get_collision_buffer_item(_MYID);    
                        temp->succ = col_item;
                        col_item->data_addr = address;
                        //slave_new_update_hashitem(access, col_item);
                        predecessor=col_item->data_access;
                        slave_add_succ(access, predecessor); //依赖边追加和前驱计数更新
                        col_item->data_access=access; //更新哈希表
                update_complete:
                        ;
             //printf("@@@@@@@slave_initialize%d\n",k);
                }
                 //printf("##slave_initialize%d\n",k);
// #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//     buil_prof[SUB_BUILD_RELA]+=(rtc()-reg_start);  
// #endif
            }
        
            asm volatile ("memb\n");
            //buffer_owner[own_buf_idx] = BUF_OWNER_MASTER;  //分析完512个df之后控制权移交主核
          
            // flush_slave_cache();
            // buffer_owner[own_buf_idx]=&buffer_own;
             buffer_own[own_buf_idx]=BUF_OWNER_MASTER;  //分析完512个df之后控制权移交主核
            // buffer_owner[own_buf_idx]=BUF_OWNER_MASTER;
#ifdef DEBUG_CONCURRENT  
              printf("依赖分析结束MYID%down_buf_idx%dbuffer_owner%d\n",_MYID,own_buf_idx,buffer_own[own_buf_idx]);
#endif

#ifdef DUE_IDLE
    own_buf_idx++;
    if( own_buf_idx==HELPER_BUFFER_COUNT) 
    own_buf_idx= own_buf_idx% HELPER_BUFFER_COUNT; 
     //换下一个buff，main_buf_idx[slave_id]=0，则切换1，等于1则切换0
 
#else
    own_buf_idx = (own_buf_idx+ 1) % HELPER_BUFFER_COUNT;  //换另一个buff，main_buf_idx[slave_id]=0，则切换1，等于1则切换0

#endif
            buffer_owner[own_buf_idx]=&buffer_own[own_buf_idx];
            build_end=1;  //依赖分析结束
            // printf("修改%dbuffer%d\n",_MYID,own_buf_idx);

#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    // buil_prof[SLAVE_RECV_MESS]+=(rtc()-recv_mess);
    reg_access_end=rtc();
    all_pure_register_time[_MYID]+=(double)(reg_access_end-reg_access_start)/SFREQ;
#endif

        }
        else {
            if (main_finished&&build_end) {  //此时主核没有把权限移交给从核，但是主核已经发完所有的数据流消息       
             // //依赖分析结束&&到达一个窗口，或者是spawn_and_wait（全部DFs发送完毕）
             //printf("**********main_finished%d*********\n",_MYID);
            //  printf("MYID%dcollision_item_count%d\n",_MYID,collision_item_count);
#ifdef MASTER_UNION_TOP
             printf("MYID%d往主存ltid%d发latent top,个数%d\n",_MYID,ltid,topnum);
				volatile unsigned long dma_reply = 0;
                int topsize=sizeof(void *)*topnum;
				athread_put(PE_MODE, &(local_top1[0]), &local_task_top[ltid][0], topsize, (void*)&dma_reply, 0, 0);                	
                    while (dma_reply != 1)
                ;  
                topnum=0; //写完重置
                //latent top全部写入主存之后
				 printf("_MYID%d号从核latent_top写入主存完成\n",_MYID);

#endif   
// #ifdef FLAT_CONSTRUCT_HELPER_WINDOW
//                //每一个窗口的结尾要保证heleper构图的同步性
//                slave_finished= 1; 
//                 for (i = 8; i < 8+HELPER_NUM; i++) {  //helper已经全部关闭
//                 int *finish=remote_ldm(i,slave_finished);
//                     if (*finish == 0) {
//                         break;
//                     }
//                 }
//                 //下面这个方法会卡死
// 				// slave_finished[_MYID] = 1;   
//                 // for (i = 8; i < 8+HELPER_NUM; i++) {  //helper已经全部关闭
//                 //     if (slave_finished[i] == 0) {
//                 //         break;
//                 //     }
//                 // }
//                 if (i == 8+HELPER_NUM) {
//                     // printf("***********此窗口依赖分析结束**********\n");
// #endif
#ifdef SLAVE_UNION_TOP
//窗口的df已经分析完毕，可以让7号从核合并top task
         printf("helper全都分析完本窗口所包含的依赖\n");
         int *top_union=remote_ldm(7,top_sig);
         *top_union=1;
#endif
//重新初始化哈希表
        //init_slave_buffer_and_table(_MYID); //初始化哈希表和buffer，开销太大，不建议选用

 #ifdef FLAT_CONSTRUCT_HELPER_WINDOW
                    cons_over = 0;
                   //slave_finished = 0;
                    main_finished=0;
                    build_end=0;
 #endif
                   
                   
                    exit_sig = 1; 
                    asm volatile ("memb\n");
                   break;
// #ifdef FLAT_CONSTRUCT_HELPER_WINDOW
//                 }
// #endif
            }
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    // buil_prof[SLAVE_RECV_MESS]+=(rtc()-recv_mess);
    reg_access_end=rtc();
    all_pure_register_time[_MYID]+=(double)(reg_access_end-reg_access_start)/SFREQ;
#endif
        }

    }   
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
		 add_succ_end=rtc();
		all_pure_addsucc_time[_MYID]+=(double)(add_succ_end-add_succ_start)/SFREQ;
#endif

}
